#include <array>
#include <benchmark/benchmark.h>
#include <cstdint>
#include <random>
#include <vector>

enum class Side : int16_t { SELL = -1, BUY = 1 };

struct Fill {
    Side side;
    int  qty;
};

static std::vector<Fill> make_fills(std::size_t count) {
    std::vector<Fill> fills;
    fills.reserve(count);

    std::mt19937_64 rng{42};                  // 固定种子保证可重复
    std::uniform_int_distribution<int> dist(0, 1);

    constexpr int FILL_QTY = 10;
    for (std::size_t i = 0; i < count; ++i) {
        const Side side = dist(rng) ? Side::BUY : Side::SELL;
        fills.push_back(Fill{side, FILL_QTY});
    }
    return fills;
}

// 带分支实现
static int process_with_branching(const std::vector<Fill>& fills) {
    int position      = 0;
    int last_buy_qty  = 0;
    int last_sell_qty = 0;

    for (const auto& fill : fills) {
        if (fill.side == Side::BUY) {
            position += fill.qty;
            last_buy_qty = fill.qty;
        } else if (fill.side == Side::SELL) {
            position -= fill.qty;
            last_sell_qty = fill.qty;
        }
    }
    return position + last_buy_qty + last_sell_qty;
}

// 无分支实现
static int process_without_branching(const std::vector<Fill>& fills) {
    int position = 0;
    std::array<int, 3> last_qty{0, 0, 0};

    auto side_to_int = [](Side side) noexcept {
        return static_cast<int16_t>(side);
    };

    for (const auto& fill : fills) {
        const int16_t int_side = side_to_int(fill.side);
        position += int_side * fill.qty;
        last_qty[int_side + 1] = fill.qty;
    }
    return position + last_qty[0] + last_qty[2];
}

// Google Benchmark: 带分支
static void BM_WithBranching(benchmark::State& state) {
    const std::size_t num_fills = static_cast<std::size_t>(state.range(0));

    state.PauseTiming();
    const auto fills = make_fills(num_fills);
    state.ResumeTiming();

    for (auto _ : state) {
        benchmark::DoNotOptimize(process_with_branching(fills));
    }
    state.SetItemsProcessed(state.iterations() * num_fills);
}

// Google Benchmark: 无分支
static void BM_Branchless(benchmark::State& state) {
    const std::size_t num_fills = static_cast<std::size_t>(state.range(0));

    state.PauseTiming();
    const auto fills = make_fills(num_fills);
    state.ResumeTiming();

    for (auto _ : state) {
        benchmark::DoNotOptimize(process_without_branching(fills));
    }
    state.SetItemsProcessed(state.iterations() * num_fills);
}

BENCHMARK(BM_WithBranching)->Arg(1'000'000)->Arg(5'000'000);
BENCHMARK(BM_Branchless)->Arg(1'000'000)->Arg(5'000'000);

BENCHMARK_MAIN();